defmodule Util do
	@moduledoc false

	def uuid() do
		SnowIdLib.get_string!()
	end


	def random_char_string(length) do
		{a, _} = :crypto.rand_plugin_next(0)
		a
		|> :erlang.integer_to_binary
		|> binary_part(0, length)
		|> :erlang.binary_to_list()
		|> Enum.map(&(&1 + ?a - ?1 + 1))
		|> :erlang.list_to_binary()
	end


	def random_up_string(length) do
		:crypto.strong_rand_bytes(length)
		|> Base.url_encode64()
		|> binary_part(0, length)
		|> String.upcase()
	end


	def random_num_string(length) do
		{a, _} = :crypto.rand_plugin_next(0)
		a
		|> :erlang.integer_to_binary
		|> binary_part(0, length)
	end

	def random_num(curs, len) do
		random_num(curs, random_num_string(len), len)
	end

	def random_num(curs, num, len) when is_list(curs) do
		if num in curs do
			random_num(curs, random_num_string(len), len)
		else
			num
		end
	end
	def random_num(curs, num, len) when Kernel.is_map(curs) do
		if Map.has_key?(curs, num) do
			random_num(curs, random_num_string(len), len)
		else
			num
		end
	end

	def iif(condition, true_result, false_result) do
		if condition do
			true_result
		else
			false_result
		end
	end

	def del_price(price) when is_binary(price)do
		case Integer.parse(price) do
			{p, _} ->
				p
			:error ->
				:error
		end
	end
	def del_price(price) do
		to_integer(price)
	end

	def to_atom(str) when is_binary(str) do
		String.to_existing_atom(str)
	end
	def to_atom(str) when is_atom(str) do
		str
	end
	def to_atom(_) do
		:error
	end

	def binary_to_list(str) when is_binary(str) do
		case Jason.decode(str) do
			{:ok, r} ->
				r
			_ ->
				:error
		end
	end
	def binary_to_list(str) do
		str
	end

	# array[integer/string,integer/string] -> string
	def list_to_binary(label)do
		{:ok, r} = Jason.encode(label)
		r
	end

	def list_ele_to_integer(str) when is_binary(str) do
		case Jason.decode(str) do
			{:ok, list} ->
				list_ele_to_integer(list)
			_ ->
				[]
		end
	end
	def list_ele_to_integer(list) when is_list(list) do
		Enum.reduce(
			list,
			[],
			fn (h, acc) ->
				case Enum.member?(acc, h) do
					true ->
						acc
					_ ->
						[to_integer(h) | acc]
				end
			end
		)
	end

	def to_integer(value) when is_integer(value) do
		value
	end
	def to_integer(value) when is_binary(value) do
		case Integer.parse(value) do
			{i, _} ->
				i
			err ->
				err
		end
	end
	def to_integer(value) when is_float(value) do
		to_integer(Float.to_string(value))
	end
	def to_integer(_) do
		nil
	end

	def to_string(str) when is_integer(str) do
		Integer.to_string(str)
	end
	def to_string(str) when is_float(str) do
		Float.to_string(str)
	end
	def to_string(str) do
		str
	end

	def to_float("") do
		""
	end
	def to_float(i) when is_binary(i) do
		Float.parse(i)
		|> case do
				 :error ->
					 ""
				 {f, _} ->
					 f
			 end
	end
	def to_float(int) do
		{f, _} = Float.parse(Util.to_string(int))
		f
	end

	def to_bool(bool) when is_binary(bool) do
		Jason.decode!(bool)
	end
	def to_bool(bool) do
		bool
	end

	def one_day_sec() do
		86400
	end

	def one_hour() do
		60 * 60
	end

	def return_msg(cmd, error_code) do
		%{
			cmd: cmd,
			error_code: error_code
		}
	end

	def return_msg(cmd, error_code, data) do
		%{
			cmd: cmd,
			error_code: error_code,
			data: data
		}
	end

	def web_socket_return(cmd, err_code) do
		%{
			cmd: cmd,
			error_code: err_code
		}
		|> Jason.encode!()
	end

	def web_socket_return(cmd, error_code, data) do
		%{
			cmd: cmd,
			error_code: error_code,
			data: data
		}
		|> Jason.encode!()
	end

	def default_str() do
		inspect(" ")
	end

	def clear_node_id(pid) do
		[_, p1, p2] = String.split(inspect(pid), ".")
		"<0." <> p1 <> p2
	end

	def get_function({fun, _}) do
		fun
	end
	defmacro get_function() do
		__CALLER__.function
		|> get_function()
	end

	def ele_is_integer(list) do
		Enum.all?(
			list,
			fn (h) ->
				is_integer(h)
			end
		)
	end


	def parse_condition("") do
		[]
	end
	def parse_condition(str) do
		String.split(str, ",")
	end

	def ts_ymd_hms(field) do
		"to_char(#{field}, 'yyyy-MM-dd hh24:MI:ss') #{field}"
	end

	def ts_ymd_hms(field, alias) do
		"to_char(#{field}, 'yyyy-MM-dd hh24:MI:ss') #{alias}"
	end

	def read_string(binary) do
		s = for c <- binary,
						into: "",
						do:
							<<c>>
		s
		|> IO.puts()
	end

	def raw_binary_to_string(raw) do
		codepoints = String.codepoints(raw)
		Enum.reduce(
			codepoints,
			fn (w, result) ->
				cond do
					String.valid?(w) ->
						result <> w
					true ->
						<<parsed :: 8>> = w
						result <> <<parsed :: utf8>>
				end
			end
		)
	end

	def to_pid(str) do
		[n, i, d] = String.split(str, ".")
		:c.pid(String.to_integer(n), String.to_integer(i), String.to_integer(d))
	end
	def to_pid2(pid_str) do
		[_, str] = String.split(pid_str, "<")
		[n, i, d] = String.split(str, ">")
								|> hd
								|> String.split(".")
		:c.pid(String.to_integer(n), String.to_integer(i), String.to_integer(d))
	end

	@err_code :err_code
	def put_err_code(err) do
		Process.put(@err_code, err)
	end

	def erase_err_code() do
		:erlang.erase(@err_code)
	end
end
